﻿using System;
using System.Linq;
using JetBrains.Annotations;
using StreetPacMan.Server.Facade;
using StreetPacMan.Server.Rules;
using StreetPacMan.Server.Rules.PlayerLocationChangeRules;

namespace StreetPacMan.Server
{
    public interface IPlayerLocationChangedHandler
    {
        void Handle(ServerPollParameters serverPollParameters);
    }

    [UsedByIoc]
    public class PlayerLocationChangedHandler : IPlayerLocationChangedHandler
    {
        private readonly IConnectionProvider _ConnectionProvider;
        private readonly IHandlePlayerLocationChangedRule[] _Rules;

        public PlayerLocationChangedHandler(IConnectionProvider connectionProvider)
        {
            _ConnectionProvider = connectionProvider;
            _Rules = new IHandlePlayerLocationChangedRule[]
                         {
                             new AddPollingEventRule(),
                             new UpdateEntityDataRule(),
                             new UpdateLocationRule(),
                             new ChangeGameStateFromSuperPacManToNormalIfTimeOverRule(),
                             new StartGameByPacManRule(),
                             new ApplesEatingRule(),
                             new PacManGhostCollisionRule()
                         };
        }

        public void Handle(ServerPollParameters serverPollParameters)
        {
            using (var dbConnection = _ConnectionProvider.GetConnection())
            using (var pacManDataContext = new PacManDataContext(dbConnection))
            {
                var player = pacManDataContext.Players.Where(x => x.Id == serverPollParameters.EntityId).FirstOrDefault();
                if(player==null)
                {
                    throw new ArgumentException(string.Format("Player id '{0}' does not exist", serverPollParameters.EntityId));
                }

                if (serverPollParameters.IsEnabled==false || 
                    player.StateEnum == PlayerState.JoinedEatenNotPlaying)
                {
                    return;
                }

                bool shouldContinueHandling=true;
                foreach (var handlePlayerLocationChangedRule in _Rules)
                {
                    handlePlayerLocationChangedRule.Handle(pacManDataContext, serverPollParameters, ref shouldContinueHandling);
                    if(shouldContinueHandling==false)
                    {
                        break;
                    }
                }
                pacManDataContext.SubmitChanges();
            }
        }
    }
}